//---- Editor


function Editor() {
	this.timeout = null;
	this.last = null;
	this.oCursor = {x: 0, y: 0};
	this.onChangePosition = null; // function(x, y)
	this.onCheckKeyword = null; // function(line)
	this.onChange = null;
	this.onKeyUp = null; // function(char)
	this.onKeyDown = null; // function(char)	
}

Editor.prototype.getValue = function() {
	return this.el.getCode();
}

Editor.prototype.getSelected = function() {
	return this.el.contentWindow.getSelection().toString().stripHTML();
}

Editor.prototype.setValue = function(s) {
	s = s.toString();
	this.el.setCode(s);
	return s;
}

Editor.prototype.postChange = function() {
	if (this.onChange) {
		if (this.last != this.el.value) {
			this.last = this.el.value;
			this.onChange();
		}
	}
}

Editor.prototype.init = function(oFrame) {
	var editor = this;
	this.el = oFrame;
	this.el.handleKeyDown = function(e, c) { editor.handleKeyDown(e, c); }
	this.el.handleKeyUp = function(e, c) { editor.handleKeyUp(e, c); editor.checkPosition(e); editor.resetTimer(); }
	/*
	// FIXME: REGRESSION
	if (!is_ie)
		this.el.oninput = function(e) { editor.checkPosition(e); editor.resetTimer(); }
	else
		this.el.onpaste = function(e) { editor.checkPosition(e); editor.resetTimer(); }
	*/
}

Editor.prototype.checkPosition = function() {
	var oSel = this.el.contentWindow.getSelection();
	var oNode = oSel.anchorNode;
	var iPos = oSel.anchorOffset;
	
	if (oNode)
		oNode = findAnchorNodeMIDAS(oNode, iPos, true);
		
	// position indicator (Gecko MIDAS is a real bitch when it comes to this)	
	var iX = 0, iY = 0;
	var bKeySearch = !!this.onCheckKeyword;
	var aWords = [];
	if (oNode) {		
		var oLimit = this.el.contentWindow.document.body;
		traverseBackwards(oNode, oLimit, function(oNode, bIsText) {
			if (bIsText) {
				if (iY == 0) {
					iX += (oNode == oSel.anchorNode) ? iPos : oNode.nodeValue.length;
				}								
				if (bKeySearch) {
					// accumulate keywords
					aWords.unshift(oNode.nodeValue);
				}
			} else
			if (oNode.tagName == 'BR') {
				iY++;
				bKeySearch = false;
			}
		});
	}
	
	if (aWords.length) {
		var sText = aWords.join('');
		var iFrom = scanLeft(sText, (iPos == 0) ? 0 : iPos-1, "\n");
		var iTo = scanRight(sText, iPos, "\n;");
		var sLine = sText.substr(iFrom, iTo-iFrom + 1);
		this.onCheckKeyword(sLine);	
	}
	
	this.oCursor.x = iX;
	this.oCursor.y = iY;
	(this.onChangePosition) && (this.onChangePosition(this.oCursor.x, this.oCursor.y));
}

Editor.prototype.resetTimer = function() {
	if (this.timeout)
		clearTimeout(this.timeout);
	var editor = this;
	this.timeout = setTimeout(function() { editor.postChange() }, 1000);
}

Editor.prototype.gotoLine = function(iLine) {
	var oNode = findLineMIDAS(this.el.contentWindow.document.body, iLine);
	var oSel = this.el.contentWindow.getSelection();
	oSel.removeAllRanges();
	var oRange = this.el.contentWindow.document.createRange();
	try {
		if (oNode) {
			oRange.setStartAfter(oNode);			
		} else {
			oNode = this.el.contentWindow.document.body.firstChild;
			oRange.setStartBefore(oNode);
		}
		oNode.scrollIntoView(true);
	} catch (e) {}
	oRange.collapse(true);
	oSel.addRange(oRange);
	this.el.contentWindow.focus();
	editor.checkPosition();
}

Editor.prototype.autoIndent = function() {
	var oSel = this.el.contentWindow.getSelection();
	var oNode = findAnchorNodeMIDAS(oSel.anchorNode, oSel.anchorOffset);	
	var aText = [];
	var sTabs;
	traverseBackwards(oNode, this.el.contentWindow.document.body, function(oNode, bIsText) {
		if (!bIsText) {
			if (oNode.tagName == 'BR') {
				if (aText.length > 0) {
					sTabs = aText.join('').replace(/[^\t].*/, '');
					aText.length = 0;
					return true;
				}				
			}
		} else {
			// it's not push, since we're traversing backwards
			aText.unshift(oNode.nodeValue);
		}
	});
	if (aText.length)
		sTabs = aText.join('').replace(/[^\t].*/, '');
	this.el.editor.insertCode(sTabs, false);
}

Editor.prototype.indentSelection = function(bUnindent) {
	var oSel = this.el.contentWindow.getSelection();
	if (oSel.rangeCount <= 0)
		return;
	var oRange = oSel.getRangeAt(0);
	if (oRange.collapsed)
		return;
	var oStart = findAnchorNodeMIDAS(oRange.startContainer, oRange.startOffset);
	var oEnd = findAnchorNodeMIDAS(oRange.endContainer, oRange.endOffset, true);
	var oPrev = null;
	//console.log(oStart, oEnd, oRange.endContainer, oRange.endOffset);
	traverseBackwards(oEnd, this.el.contentWindow.document.body, function(oNode, bIsText) {
		if (!bIsText) {
			if (oNode.tagName == 'BR' && oPrev) {
				if (bUnindent)
					oPrev.nodeValue = oPrev.nodeValue.replace(/^\t/, '');
				else
					oPrev.nodeValue = "\t" + oPrev.nodeValue;
				oPrev = null;
			}
		} else {
			oPrev = oNode;
		}
		if (oNode == oStart)
			return true;
	});
	if (oPrev) {
		if (bUnindent)
			oPrev.nodeValue = oPrev.nodeValue.replace(/^\t/, '');
		else
			oPrev.nodeValue = "\t" + oPrev.nodeValue;
	}
	return false;
}

